package com.avalon.core.orm;

import javassist.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.util.ClassUtils;

import java.util.List;


/**
 * 动态生成模型工具类
 *
 * @author lwlianghehe@gmail.com
 * @date 2024/12/06 9:27
 */
@Slf4j
public class ClassPoolManager {
    /**
     * 模型动态继承
     *
     * @param classPool    模型修改器
     * @param parentClass  父类
     * @param childClasses 子类
     * @return
     * @throws NotFoundException
     * @throws CannotCompileException
     */
    public static Class<?> createEnhancedClass(ClassPool classPool,
                                               Class<?> parentClass,
                                               List<Class<?>> childClasses)
            throws NotFoundException, CannotCompileException {
        CtClass parentCtClass = classPool.get(parentClass.getName());
        CtClass childCtClass = null;
        Class<?> targetClass = null;
        for (Class<?> childClass : childClasses) {
            childCtClass = classPool.get(childClass.getName()); // 子类
            // 设置继承关系
            childCtClass.setSuperclass(parentCtClass);

            String newClassName = childClass.getName() + "$Enhanced_" + System.currentTimeMillis();
            childCtClass.setName(newClassName);
            //  加载类到当前类加载器
            if (getAppClassLoader().equals(getDefaultClassLoader())) { // 如果是同一个加载器，则加载一个
                targetClass = childCtClass.toClass(getAppClassLoader());
            } else { // 在tomcat下，有两个加载器，则同时加载
                targetClass = childCtClass.toClass(getAppClassLoader());
                targetClass = childCtClass.toClass(getDefaultClassLoader());
            }

            parentCtClass = childCtClass;
        }

        return targetClass;
    }

    /**
     * 创建类修改器
     *
     * @return
     */
    public static ClassPool createClassPool() {
        try {
            // 2. 获取当前上下文的类加载器
            ClassLoader contextClassLoader = getDefaultClassLoader();
            ClassPool classPool = ClassPool.getDefault();
            classPool.appendClassPath(new LoaderClassPath(contextClassLoader));
            return classPool;
        } catch (Exception e) {
            throw new IllegalStateException("Failed to create ClassPool", e);
        }
    }

    public static ClassLoader getDefaultClassLoader() {
        return ClassUtils.getDefaultClassLoader(); // 如果是接口
    }

    public static ClassLoader getAppClassLoader() {
        return ClassUtils.class.getClassLoader();
    }
}
